package cn.tnar.parkservice.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 日期相关工具类
 */
public final class DateUtils {

    public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static final String YYYYMMDDHHMMSSSSS = "yyyyMMddHHmmssSSS";

    public static final String YYYY_MM_DD = "yyyy-MM-dd";

    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    public static final String YYYYMMDD = "yyyyMMdd";

    public static final String YYYYMM = "yyyyMM";

    public static final String YYYY = "yyyy";

    public static final String HHMMSS = "HHmmss";

    public static final String HH_MM_SS = "HH:mm:ss";

    /**
     * 使用ThreadLocal管理时间格式化对象
     */
    private static ThreadLocal<Map<String, SimpleDateFormat>> threadLocal = ThreadLocal.withInitial(HashMap::new);

    /**
     * 从ThreadLocal中获取时间格式化对象
     *
     * @param dateType 时间类型
     * @return 格式化后的时间串
     */
    private static SimpleDateFormat getDateFormat(final String dateType) {
        Map<String, SimpleDateFormat> map = threadLocal.get();
        SimpleDateFormat df = map.get(dateType);
        if (df == null) {
            df = new SimpleDateFormat(dateType);
            map.put(dateType, df);
        }
        return df;
    }

    /**
     * 将日期装换成指定格式的字符串
     *
     * @param format 格式
     * @param date   日期
     * @return String
     */
    public static String getTimeString(String format, Date date) {
        if (date == null) {
            return null;
        }
        return getDateFormat(format).format(date).trim();
    }

    /**
     * 将当前时间装换成指定格式的字符串
     *
     * @param format 格式
     * @return String
     */
    public static String getNowString(String format) {
        return getTimeString(format, new Date());
    }

    /**
     * 日期解析
     *
     * @param format  format
     * @param strDate strDate
     * @return Date
     */
    public static Date parse(String format, String strDate) {
        try {
            return getDateFormat(format).parse(strDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取指定日期的
     *
     * @param date     日期
     * @param timeType 日期类型(年、月、周、日)Calendar.MONTH...
     * @return 当前数(第几日 周 月 年..)
     */
    private static int getNumByDate(final Date date, final int timeType) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        return calendar.get(timeType);
    }

    /**
     * 获取指定日期当前年份中的月数
     *
     * @param date 日期
     * @return 第几月 eg: 20160826 ->8
     */
    @SuppressWarnings("unused")
    public static int getMonthNum(final Date date) {
        return getNumByDate(date, Calendar.MONTH) + 1;
    }

    /**
     * 获取指定时间当前年份中的周数
     *
     * @param date 日期
     * @return 第几周 eg:20160826 ->35
     */
    @SuppressWarnings("unused")
    public static int getWeekNum(final Date date) {
        return getNumByDate(date, Calendar.WEEK_OF_YEAR);
    }

    /**
     * 获取指定时间当前月份中的日数的前一日
     *
     * @param date 日期
     * @return 第几日 eg:20160826 ->25
     */
    @SuppressWarnings("unused")
    public static int getLastDayNum(final Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -1);

        return calendar.get(Calendar.DAY_OF_MONTH);
    }


    /**
     * 获取日期对应的星期
     *
     * @param date date
     * @return int
     */
    @SuppressWarnings("unused")
    public static int getDayOfWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int retval = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        if (retval == 0) {
            retval = 7;
        }

        return retval;
    }

    /**
     * 日期比较
     *
     * @param format  日期字符串格式
     * @param dateStr 日期字符串
     * @param date    日期
     * @return true/false dateStrTime < dateTime
     */
    @SuppressWarnings("unused")
    public static boolean compareTime(String format, String dateStr, Date date) {
        Date time = parse(format, dateStr);
        return time != null && date != null && time.getTime() < date.getTime();
    }

    /**
     * 获取上周周数
     *
     * @param date 日期
     * @return 上周第几周
     */
    @SuppressWarnings("unused")
    public static int getLastWeekNum(final Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        // 上周
        calendar.add(Calendar.WEEK_OF_YEAR, -1);

        return calendar.get(Calendar.WEEK_OF_YEAR);
    }

    /**
     * 获取指定日期上一个月份中的月数
     *
     * @param date 日期
     * @return 指定日期上一个月份中的月数
     */
    @SuppressWarnings("unused")
    public static int getLastMonthNum(final Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, -1);

        return calendar.get(Calendar.MONTH) + 1;
    }

    /**
     * 分年月日查询时 拼接查询时间
     *
     * @param queryDate
     * @return
     */
    public static long queryDate2startTime(String queryDate) {
        int length = queryDate.length();
        long startTime = 0l;
        if (length == 8) {
            startTime = Long.valueOf(queryDate + "000000");
        } else if (length == 6) {
            startTime = Long.valueOf(queryDate + "01000000");
        } else if (length == 4) {
            startTime = Long.valueOf(queryDate + "0101000000");
        }
        return startTime;
    }

    /**
     * 分年月日查询时 拼接查询时间
     *
     * @param queryDate
     * @return
     */
    public static long queryDate2endTime(String queryDate) {
        int length = queryDate.length();
        long endTime = 0l;
        if (length == 8) {
            endTime = Long.valueOf(queryDate + "235959");
        } else if (length == 6) {
            endTime = Long.valueOf(queryDate + "31235959");
        } else if (length == 4) {
            endTime = Long.valueOf(queryDate + "1231235959");
        }
        return endTime;
    }

    /**
     * 获取当前时间
     *
     * @return
     */
    public static String getTime() {
        Calendar Cld = Calendar.getInstance();
        DateTimeFormatter DATE_TIME = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String time = DATE_TIME.format(LocalDateTime.now());
        return time;
    }

    /**
     * 获取当前时间:年月日
     *
     * @return
     */
    public static String getTimeYMD() {
        Calendar Cld = Calendar.getInstance();
        DateTimeFormatter DATE_TIME = DateTimeFormatter.ofPattern("yyyyMMdd");
        String time = DATE_TIME.format(LocalDateTime.now());
        return time;
    }


    /**
     * 获得该月第一天
     *
     * @param year
     * @param month
     * @return
     */
    public static String getFirstDayOfMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        // 设置年份
        cal.set(Calendar.YEAR, year);
        // 设置月份
        cal.set(Calendar.MONTH, month - 1);
        // 获取某月最小天数
        int firstDay = cal.getActualMinimum(Calendar.DAY_OF_MONTH);
        // 设置日历中月份的最小天数
        cal.set(Calendar.DAY_OF_MONTH, firstDay);
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String firstDayOfMonth = sdf.format(cal.getTime());
        return firstDayOfMonth;
    }

    /**
     * 获得该月最后一天
     *
     * @param month
     * @return
     */
    public static String getLastDayOfMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        // 设置年份
        cal.set(Calendar.YEAR, year);
        // 设置月份
        cal.set(Calendar.MONTH, month - 1);
        // 获取某月最大天数
        int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
        // 设置日历中月份的最大天数
        cal.set(Calendar.DAY_OF_MONTH, lastDay);
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String lastDayOfMonth = sdf.format(cal.getTime());
        return lastDayOfMonth;
    }

    public static int differentDaysByMillisecond(Date date1,Date date2)
    {
        int days = (int) ((date2.getTime() - date1.getTime()) / (1000*3600*24));
        return days;
    }

    public static String getAddMonth(int month){
        Calendar curr = Calendar.getInstance();
        curr.set(Calendar.MONTH,curr.get(Calendar.MONTH)+month); //增加一月
        Date date=curr.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dateNowStr = sdf.format(date);
        return dateNowStr;
    }

    public static String addMonth(String strDate,int month){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Calendar curr = Calendar.getInstance();
        try {
            Date date = sdf.parse(strDate);
            curr.setTime(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        curr.set(Calendar.MONTH,curr.get(Calendar.MONTH)+month); //增加一月
        Date date1=curr.getTime();

        String dateNowStr = sdf.format(date1);
        return dateNowStr;
    }

    public  static String subMonth(String date,int month) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Date dt = sdf.parse(date);
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(dt);
        rightNow.add(Calendar.MONTH, month);
        Date dt1 = rightNow.getTime();
        String reStr = sdf.format(dt1);
        return reStr;
    }

    /**
     * 根据开始时间，结束时间 计算时间差
     * 以 xx天xx时xxfen的形式返回
     * @param startTime
     * @param endTime
     * @return
     */
    public static String getTimeDiff(Long startTime,Long endTime){
        long nd = 1000*60*60*24;
        long nh = 1000*60*60;
        long nm = 1000*60;

        String startStr = startTime.toString();
        String endStr = endTime.toString();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        try {
            Date start = sdf.parse(startStr);
            Date end = sdf.parse(endStr);
            long diff = end.getTime()-start.getTime();
            long day = diff / nd;
            long hour = diff % nd /nh;
            long min = diff % nd % nh /nm;
            return day+"天"+hour+"小时"+min+"分";
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

}
